import { createClient } from '@supabase/supabase-js'
import { NextResponse } from 'next/server'
// Create server-side Supabase client with service role for admin operations
function createServerSupabaseClient() {
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY
if (!serviceRoleKey) {
throw new Error('SUPABASE_SERVICE_ROLE_KEY is not set')
}
return createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
serviceRoleKey,
{
auth: {
autoRefreshToken: false,
persistSession: false
}
}
)
}
// GET /api/books/[id] - Get a specific book
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const bookId = params.id
const url = new URL(request.url)
const userId = url.searchParams.get('userId')
if (!userId) {
return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
}
const supabase = createServerSupabaseClient()
const { data: book, error } = await supabase
.from('books')
.select(`
id,
title,
description,
status,
word_count,
created_at,
updated_at,
author,
genre,
target_word_count,
cover_image_url
`)
.eq('id', bookId)
.eq('user_id', userId)
.single()
if (error) {
console.error('Error fetching book:', error)
return NextResponse.json({ error: 'Book not found' }, { status: 404 })
}
const transformedBook = {
...book,
lastModified: book.updated_at.split('T')[0],
}
return NextResponse.json({ book: transformedBook })
} catch (error) {
console.error('Unexpected error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}
// PUT /api/books/[id] - Update a specific book
export async function PUT(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const bookId = params.id
const body = await request.json()
if (!body.userId) {
return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
}
if (!body.title || body.title.trim() === '') {
return NextResponse.json({ error: 'Title is required' }, { status: 400 })
}
const supabase = createServerSupabaseClient()
// Handle genres - convert array to comma-separated string or use string directly
const genreValue = Array.isArray(body.genres) && body.genres.length > 0
? body.genres.join(', ')
: body.genre?.trim() || null
const { data: book, error } = await supabase
.from('books')
.update({
title: body.title.trim(),
description: body.description?.trim() || null,
author: body.author?.trim() || null,
genre: genreValue,
target_word_count: body.target_word_count || null,
status: body.status || undefined,
cover_image_url: body.cover_image_url || undefined,
updated_at: new Date().toISOString()
})
.eq('id', bookId)
.eq('user_id', body.userId)
.select()
.single()
if (error) {
console.error('Error updating book:', error)
return NextResponse.json({ error: 'Failed to update book' }, { status: 500 })
}
const transformedBook = {
...book,
lastModified: book.updated_at.split('T')[0],
}
return NextResponse.json({ book: transformedBook })
} catch (error) {
console.error('Unexpected error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}
// DELETE /api/books/[id] - Delete a specific book
export async function DELETE(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const bookId = params.id
const url = new URL(request.url)
const userId = url.searchParams.get('userId')
if (!userId) {
return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
}
const supabase = createServerSupabaseClient()
// First, delete all book files and folders
const { error: filesError } = await supabase
.from('file_system_items')
.delete()
.eq('book_id', bookId)
if (filesError) {
console.error('Error deleting book files:', filesError)
return NextResponse.json({ error: 'Failed to delete book files' }, { status: 500 })
}
// Then delete the book itself
const { error: bookError } = await supabase
.from('books')
.delete()
.eq('id', bookId)
.eq('user_id', userId)
if (bookError) {
console.error('Error deleting book:', bookError)
return NextResponse.json({ error: 'Failed to delete book' }, { status: 500 })
}
return NextResponse.json({ message: 'Book deleted successfully' })
} catch (error) {
console.error('Unexpected error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}